#ifndef SIGNAL_WATCHER_H
#define SIGNAL_WATCHER_H

#include <uv.h>
#include <cstring>
#include <functional>
#include <unordered_set>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>

#define MAKE_NONCOPYABLE(T) T(const T&) = delete; T& operator=(const T&) = delete
#define sk_error(fmt, ...) do { \
    printf("ERROR:file<%s>:line<%d>:function<%s>", __FILE__, __LINE__, __func__);\
    printf(fmt, ##__VA_ARGS__);\
    printf("\n");\
} while(0)

#define unlikely(x) __builtin_expect(!!(x), 0)
using fn_on_signal_event = std::function<void(const struct signalfd_siginfo*)>;

class signal_watcher {
public:
    MAKE_NONCOPYABLE(signal_watcher);
    ~signal_watcher();

    static signal_watcher *create(uv_loop_t *loop);

    int watch(int signal);
    int unwatch(int signal);

    bool has_watch(int signal) const {
        return watched_signals_.find(signal) != watched_signals_.end();
    }

    int start();
    int stop();
    void set_signal_callback(const fn_on_signal_event& fn) { fn_on_signal_ = fn; }

private:
    signal_watcher(int signal_fd, uv_loop_t *loop);
    void on_signal();
    static void on_signal_event(uv_poll_t* poll, int status, int events);

private:
    int signal_fd_;
    uv_poll_t poll_;
    uv_loop_t *loop_;
    std::unordered_set<int> watched_signals_;

    fn_on_signal_event fn_on_signal_;
};

#endif
